#ifndef IMAGE_PAGE_MIME_H
#define IMAGE_PAGE_MIME_H



#include <QPair>
#include <QtGui>
#include <QtCore>
#include <QPixmap>

#include <QMetaType>
#define _IMAGE_PICS_ITEM_ 100

#define _LINK_COLOR_ \
             QColor("#dc0000")


class SPics
{
    public:
    enum { MAGICNUMBER = 0xFFAAFFAA, VERSION = 1 };
    SPics();
    SPics& operator=( const SPics& d );
    bool operator!=( const SPics& d );
    operator QVariant() const {
    return QVariant::fromValue(*this);
    }
    QPixmap erno_pix();
    QString web();
    QPixmap pix();
    QString FileName();
    void SavePixThread( QString dir = QString() );
    void set_pics( const QPixmap * barcode );
    void set_pics( QPixmap barcode );
    inline int picskilo() {
    return data.size();
    }
    QUrl indoc();
    /* vars permanent to put on stream  */
    QString name;
    QString info;
    QByteArray extension;
    QByteArray data;  /* qCompress */
};

Q_DECLARE_METATYPE(SPics);

inline QDebug operator<<(QDebug debug, SPics& udoc)
{
	debug.nospace() << "SPics(name." 
		<< udoc.name << "," 
    << udoc.info << ",size()"
    << udoc.data.size() << ",type()"
    << udoc.extension << ")";
	return debug.space();
}

inline QDataStream& operator<<(QDataStream& out, const SPics& udoc)
{
    out << udoc.name;
    out << udoc.info;
    out << udoc.extension;
    out << udoc.data;
    return out;
}

inline QDataStream& operator>>(QDataStream& in, SPics& udoc)
{
    in >> udoc.name;
    in >> udoc.info;
    in >> udoc.extension;
    in >> udoc.data;
    return in;
}

class RichDoc
{
    public:
    enum { MAGICNUMBER = 0xFFAAFFAA, VERSION = 2 };
    RichDoc() {
    html = QByteArray("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Your text</p>");
		style = QString("min-height:300px;padding:0px 0px 0px 0px;background-color:#ffffff;");
		nullmargin = false;
    }
		void margin( bool e )
		{
		nullmargin = e;
		}
    RichDoc& operator=( const RichDoc& d )
    {
      resource.clear();
      resource = d.resource;
      html = d.html;
      style = d.style;
			return *this;
    }
    operator QVariant() const {
    return QVariant::fromValue(*this);
    }
    
    void Register( QTextDocument *doc , QMap<QString,SPics> list , QString s )
    {
      style = s;
      html.clear();
      html.append(doc->clone()->toHtml("utf-8"));
      resource.clear();
			if (list.size() > 0) {
      resource = list;
			}
    }
		
		void Register( const QString xhtml , QMap<QString,SPics> list , QString s )
    {
      style = s;
      html.clear();
      html.append(xhtml);
			resource.clear();
			if (list.size() > 0) {
      resource = list;
			}
    }
    QString Hxtml()
		{
		return QString(html.constData());
		}
		
		bool isAbsolute()
		{
		return style.contains("position:absolute;");
		}
		
    QTextDocument *todoc()
    {
			  QTextCursor helper;
        QTextDocument *d = new QTextDocument();
        d->setHtml(QString(html));
			  helper = QTextCursor(d);
			  QMapIterator<QString,SPics> i(resource);
		     while (i.hasNext()) {
           i.next();
				   SPics record = i.value();
				   d->addResource( QTextDocument::ImageResource,QUrl(record.name),record.pix());
         }
				 QTextFrame  *Tframe = d->rootFrame();
				 if (nullmargin) {
					 
					       QTextFrameFormat Ftf = Tframe->frameFormat();
					       Ftf.setLeftMargin(0);
                 Ftf.setBottomMargin(0);
                 Ftf.setTopMargin(0);
                 Ftf.setRightMargin(0);
					       Tframe->setFrameFormat(Ftf);
				 }
				 
				 
				 QTextFrame::iterator it;
         for (it = Tframe->begin(); !(it.atEnd()); ++it) {
					 QTextBlock para = it.currentBlock();
					 if (para.isValid()) {
						QTextBlockFormat Parformat = para.blockFormat();
						if (Parformat.bottomMargin() == 12 && Parformat.topMargin() == 12 || nullmargin ) {
							Parformat.setBottomMargin(0); 
              Parformat.setTopMargin(0);
              Parformat.setRightMargin(0);
              Parformat.setLeftMargin(0);
							helper.setPosition(para.position(),QTextCursor::MoveAnchor);
							helper.setBlockFormat(Parformat);
						}
						 
						 
							QTextBlock::iterator de;
										for (de = para.begin(); !(de.atEnd()); ++de) {
												QTextFragment fr = de.fragment();
											  if (fr.isValid()) {
                           QTextCharFormat base = fr.charFormat();
                           QTextImageFormat pico = base.toImageFormat();
                                if (base.isAnchor()) {
																	  //////////////qDebug() << "### link found..... ";
																	  base.setForeground(QBrush(_LINK_COLOR_));
                                    base.setUnderlineStyle(QTextCharFormat::SingleUnderline);
																		helper.setPosition(fr.position());
                                    helper.setPosition(fr.position() + fr.length(),QTextCursor::KeepAnchor);
																	  helper.setCharFormat(base);
																}
																
													      if (pico.isValid()) {
																		const QString hrefadress = pico.name();
																		SPics spico = resource[hrefadress];
																		////////////qDebug() << "### from RichDoc add resource " << hrefadress;
																		////////////////qDebug() << "### from RichDoc info " << spico.info;
																		pico.setToolTip(spico.info);
																		pico.setProperty(_IMAGE_PICS_ITEM_,spico);
																		helper.setPosition(fr.position());
                                    helper.setPosition(fr.position() + fr.length(),QTextCursor::KeepAnchor);
                                    helper.setCharFormat(pico);
																}
												}
																 
										}
						 
					 }
			
		     }
				 

        return d;
    }
		bool nullmargin;
    QString style;
    QMap<QString,SPics> resource;
    QByteArray html;  /* qCompress */
    
};


inline QDataStream& operator<<(QDataStream& out, RichDoc& e) 
{
			
			out << e.html;
			out << e.style;
			
								 QMapIterator<QString,SPics> i(e.resource);
								 while (i.hasNext()) {
										 i.next();
										 SPics record = i.value();
										 out << record;
								 } 
								 
			return out;
}

inline QDataStream& operator>>(QDataStream& in, RichDoc& e) 
{
			
				in >> e.html;
				in >> e.style;
				while (!in.atEnd()) {
						 SPics appoint;
						 in >> appoint;
						 e.resource.insert(appoint.name,appoint);
				}
				return in;
}



Q_DECLARE_METATYPE(RichDoc);
typedef QMap<int,RichDoc> LayerList;
typedef QList<RichDoc> QLayerList;
Q_DECLARE_METATYPE(LayerList)
Q_DECLARE_METATYPE(QLayerList)




/* save pics  list stream */
QString SaveImageGroup( QList<SPics> li  );
/* decoded base64 stream to put on mysql row , file or network streams */
QList<SPics> OpenImageGroup( const QString datastream_base64   );





/* save a doc to stream */
QString SaveRichDoc( RichDoc e );
/* decoded base64 stream to put on mysql row , file or network streams */
RichDoc OpenRichDoc( const QString datastream_base64   );



/* inline stream from page format */
QByteArray HeSaveLayer( RichDoc e , const int position );
QPair<int,RichDoc> HeOpenLayer( const QByteArray stream );


class PageDoc
{
    public:
    enum { MAGICNUMBER = 0xFFFAFFAA, VERSION = 1 };
    PageDoc() {
		Listening.clear();
		binformat.clear();
		modus = 1;
		}
		
		operator QVariant() const {
    return QVariant::fromValue(*this);
    }
		int size()
		{
		return Listening.size();
		}
		
		QByteArray save()
		{
				 QString line("\n\n");
			   QByteArray bytes;
			   QByteArray signature("PAGE\n");
			   binformat.clear();
				 QMapIterator<int,RichDoc> o(Listening);
					while (o.hasNext()) {
                 o.next();
				         RichDoc record = o.value();
							   QByteArray dat = HeSaveLayer(record,o.key());
							   binformat.append(dat);
					}
					
         	QBuffer buffer(&bytes);
					if (!buffer.open(QIODevice::WriteOnly)) {
						return QByteArray();
					}
					QDataStream ds(&buffer);
					/* place header */
					ds.setVersion(QDataStream::Qt_4_2);
					ds << signature;
					ds << (quint32)MAGICNUMBER;
					ds << (quint32)VERSION;
					ds << rect;
					ds << line;
					for (int i = 0; i < binformat.size(); ++i) {
						 ds << binformat.at(i);
				   }
					buffer.close();
					QCryptographicHash formats( QCryptographicHash::Md5 );
          formats.addData(bytes);
			    smd5 = formats.result();
	        return bytes;
		}
		
		void open( QByteArray stream )
		{
			  QCryptographicHash formats( QCryptographicHash::Md5 );
        formats.addData(stream);
			  smd5 = formats.result();
			  QBuffer buffer(&stream);
				if (!buffer.open(QIODevice::ReadOnly)) {
					return;
				}
				QString infostream;
				quint32 magic, version;
				QByteArray signer;
				QDataStream ds(&buffer);
				ds.setVersion(QDataStream::Qt_4_2);
				ds >> signer;
				if ( !signer.contains(QByteArray("PAGE")) ) {
				buffer.close();
				return;
				}
				ds >> magic;
				if ( (quint32)MAGICNUMBER != magic ) {
				qWarning() << "######## PageDoc::MAGICNUMBER not ok  " << magic;
				buffer.close();
				return;
				}
				
				ds >> version;
				if ( (quint32)VERSION != version ) {
				qWarning() << "######## PageDoc::VERSION not ok  " << version;
				buffer.close();
				return;
				}
				ds >> rect;
				ds >> infostream;
				QByteArray daten;
				Listening.clear();
				 while (!ds.atEnd()) {
              ds >> daten;
							QPair<int,RichDoc> Layers = HeOpenLayer(daten);
              Listening.insert(Layers.first,Layers.second);
          }
				 buffer.close();
		}
		QRectF rect;
		QByteArray smd5; 
		int modus;
		QMap<int,RichDoc> Listening;  /* QMap<int,RichDoc> */
		QList<QByteArray> binformat;
};



Q_DECLARE_METATYPE(PageDoc);



















#endif // IMAGE_PAGE_MIME_H

